﻿using Gargoyle.Roton;
using System;
using System.Collections.Generic;
using System.Text;

namespace Gargoyle.ZZT
{
    public class Element
    {
        public delegate void ActDelegate(Game g, int index);
        public delegate void InteractDelegate(Game g, Location location, int index, ref Vector vector);
        public delegate AnsiChar DrawDelegate(Game g, Location location);

        private ElementID InternalId;
        public byte DefaultChar;
        public byte DefaultColor;
        public bool Destructible;
        public bool Pushable;
        public bool AlwaysShow;
        public bool EditorFloor;
        public bool Floor;
        public bool DrawCodeEnabled;
        public DrawDelegate DrawCode;
        public short Cycle;
        public ActDelegate ActCode;
        public InteractDelegate InteractCode;
        public byte Menu;
        public byte Key;
        public string Name;
        public string CategoryText;
        public string P1Text;
        public string P2Text;
        public string P3Text;
        public string BoardText;
        public string StepText;
        public string CodeText;
        public short Points;
        public ByteString OOPName;
        
        public Element(ElementID newID = ElementID.None, byte newChar = 32, byte newColor = 255, bool newDestructible = false, bool newPushable = false, bool newAlwaysShow = false, bool newEditorFloor = false, bool newFloor = false, bool newDrawCodeEnabled = false, DrawDelegate newDrawCode = null, short newCycle = -1, ActDelegate newActCode = null, InteractDelegate newInteractCode = null, byte newMenu = 0, byte newKey = 0, string newName = "", string newCategory = "", string newP1Text = "", string newP2Text = "", string newP3Text = "", string newBoardText = "", string newStepText = "", string newCodeText = "", short newPoints = 0)
        {
            InternalId = newID;
            DefaultChar = newChar;
            DefaultColor = newColor;
            Destructible = newDestructible;
            Pushable = newPushable;
            AlwaysShow = newAlwaysShow;
            EditorFloor = newEditorFloor;
            Floor = newFloor;
            DrawCodeEnabled = newDrawCodeEnabled;
            DrawCode = newDrawCode;
            Cycle = newCycle;
            ActCode = newActCode;
            InteractCode = newInteractCode;
            Menu = newMenu;
            Key = newKey;
            Name = newName;
            CategoryText = newCategory;
            P1Text = newP1Text;
            P2Text = newP2Text;
            P3Text = newP3Text;
            BoardText = newBoardText;
            StepText = newStepText;
            CodeText = newCodeText;
            Points = newPoints;
            OOPName = GetOOPName(Name);
        }

        private ByteString GetOOPName(string name)
        {
            List<byte> result = new List<byte>();
            ByteString nameBytes = (name);

            for (int i = 0; i < nameBytes.Length; i++)
            {
                byte character = nameBytes[i];
                if (character >= 0x60 && character <= 0x7A)
                {
                    character = (byte)(character - 0x20);
                }
                if (character >= 0x40 && character <= 0x7A)
                {
                    result.Add(character);
                }
            }

            return result.ToArray();
        }

        public ElementID Id
        {
            get
            {
                return InternalId;
            }
        }

        public string ToOOPString()
        {
            StringBuilder result;
            int length;
            char character;
            string upperName;

            result = new StringBuilder();
            upperName = Name.ToUpperInvariant();
            length = upperName.Length;

            for (int index = 0; index < length; index++)
            {
                character = upperName[index];
                if ((character >= 'A') && (character <= 'Z'))
                {
                    result.Append(character);
                }
            }
            return result.ToString();
        }

        public override string ToString()
        {
            return "Element (" + InternalId.ToString() + ")";
        }
    }

    public enum ElementID
    {
        None = 0,
        Ammo,
        Bear,
        BlinkRayH,
        BlinkRayV,
        BlinkWall,
        BoardEdge,
        Bomb,
        Boulder,
        Breakable,
        Bullet,
        Clockwise,
        Counter,
        Door,
        DragonPup,
        Duplicator,
        Empty,
        Energizer,
        Fake,
        Floor,
        Forest,
        Gem,
        Head,
        Invisible,
        Key,
        Line,
        Lion,
        Messenger,
        Monitor,
        Normal,
        Object,
        Pairer,
        Passage,
        Player,
        Pusher,
        Ricochet,
        Roton,
        Ruffian,
        Scroll,
        Segment,
        Shark,
        SliderEW,
        SliderNS,
        Slime,
        Solid,
        Spider,
        SpinningGun,
        Star,
        Stone,
        Tiger,
        Torch,
        Transporter,
        Water,
        WaterE,
        WaterN,
        WaterS,
        WaterW,
        Web,
        BlueText,
        GreenText,
        CyanText,
        RedText,
        PurpleText,
        BrownText,
        BlackText,
        User
    }
}
